package cc.vv.lkbasecomponent.base.ui.loading;

import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;

import java.util.ArrayList;

/**
 * 控制事件穿透的自定义viewgroup.事件只可穿透到指定view控件.
 *
 * @author dupeng dupeng@vv.cc
 * @date 2018/3/8
 */

public class LoadingCoverView extends RelativeLayout {

    /**
     * 可穿透事件的控件坐标
     */
    private ArrayList<Rect> mPierceLocations = new ArrayList<>();
    /**
     * 是否事件可穿透。true：不阻碍手指触摸事件 。 false:阻碍手指触摸事件,只能指定view可以收到事件。
     */
    private boolean mCanPierce = false;

    public LoadingCoverView(Context context) {
        super(context);
        init();
    }

    public LoadingCoverView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public LoadingCoverView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        if (Build.VERSION.SDK_INT >= 16) {
            setBackground(null);
        } else {
            setBackgroundDrawable(null);
        }
    }

    /**
     * 设置是否可穿透触摸事件
     *
     * @param canPierce true:此控件不做任何事件拦截。false:控件只是不拦截指定的views的事件。
     */
    public void setCanPierce(boolean canPierce) {
        mCanPierce = canPierce;
    }

    /**
     * 清空坐标数据
     */
    public void clearAllPierceViews() {
        mPierceLocations.clear();
    }

    /**
     * 添加事件可穿透控件
     *
     * @param views
     */
    public void addCanPierceViews(final View[] views) {
        if (views == null) {
            return;
        }
        postDelayed(new Runnable() {
            @Override
            public void run() {
                for (View view : views) {
                    Rect location = getViewLocation(view);
                    if (location != null) {
                        mPierceLocations.add(location);
                    }
                }
            }
        }, 200);
    }

    /**
     * 获取到view相对于屏幕的位置
     *
     * @param view
     * @return
     */
    private Rect getViewLocation(View view) {
        if (view == null) {
            return null;
        }
        if (view.getVisibility() != View.VISIBLE) {
            return null;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (!view.isAttachedToWindow()) {
                return null;
            }
        }

        //view的位置
        Rect rect = new Rect();
        if (view.getGlobalVisibleRect(rect)) {
            return rect;
        }
        return null;
    }

    /**
     * 记录down事件是否拦截.避免move等事件还进行多余的坐标判断.
     */
    private boolean isDownInPierce = false;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (mCanPierce) {
            return super.dispatchTouchEvent(ev);
        }

        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            float rawX = ev.getRawX();
            float rawY = ev.getRawY();

            boolean isInPierceLocation = isInPierceLocation(rawX, rawY);
            if (isInPierceLocation) {
                //不拦截事件
                isDownInPierce = true;
                return super.dispatchTouchEvent(ev);
            } else {
                //拦截down事件
                return true;
            }
        } else {
            if (isDownInPierce) {
                //如果down事件已经下发，那么up等事件，就不拦截。
                if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
                    //如果是抬起，或cancel，则还原标志
                    isDownInPierce = false;
                }
                return super.dispatchTouchEvent(ev);
            } else {
                //如果down事件被拦截,那么move等事件,直接拦截.
                return true;
            }
        }
    }

    /**
     * 判断这个坐标是否在可穿透控件区域.
     *
     * @param rawX
     * @param rawY
     * @return
     */
    private boolean isInPierceLocation(float rawX, float rawY) {
        for (Rect rect : mPierceLocations) {
            if (rect == null) {
                return false;
            }
            if (rawX >= rect.left && rawX <= rect.right && rawY >= rect.top && rawY <= rect.bottom) {
                //在区域内
                return true;
            }
        }
        return false;
    }


}
